package xyz.fivefaith.tool.common.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

/**
 * Jackson 工具类（含日志）
 *
 * <p>线程安全：ObjectMapper 是单例且只读配置，可直接并发使用。
 *
 * @author ZhaoAnchi
 * @version 1.0
 * @since 2025-08-07
 */
@Slf4j
public final class JacksonUtil {

    // 忽略不存在字段
    private static final ObjectMapper MAPPER =
            JsonMapper.builder()
                    // 1. 字段名排序
                    .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
                    // 2. Map 键排序
                    .enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
                    // 3. 序列化时：忽略 null, 反序列化时：保留 null（默认)
                    .defaultPropertyInclusion(
                            JsonInclude.Value.construct(
                                    JsonInclude.Include.NON_NULL, JsonInclude.Include.ALWAYS))
                    // 4. 反序列化时忽略未知字段
                    .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                    // 5. 时间写成字符串（ISO-8601）
                    .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                    // 6. 注册 Java 8 时间模块
                    .addModule(new JavaTimeModule())
                    .build();

    /* ---------- 单例访问 ---------- */

    public static ObjectMapper getMapper() {
        return MAPPER;
    }

    /* ---------- 序列化 ---------- */

    public static String toJson(Object obj) {
        try {
            String json = MAPPER.writeValueAsString(obj);
            log.debug("toJson >>> {}", json);
            return json;
        } catch (JsonProcessingException e) {
            log.error("序列化失败, obj={}", obj, e);
            throw new IllegalArgumentException("序列化失败", e);
        }
    }

    public static byte[] toJsonBytes(Object obj) {
        try {
            byte[] bytes = MAPPER.writeValueAsBytes(obj);
            log.debug("toJsonBytes >>> {} bytes", bytes.length);
            return bytes;
        } catch (JsonProcessingException e) {
            log.error("序列化失败, obj={}", obj, e);
            throw new IllegalArgumentException("序列化失败", e);
        }
    }

    /* ---------- 反序列化 ---------- */

    public static <T> T formatJson(String json, Class<T> clazz) {
        try {
            log.debug("fromJson <<< {}", json);
            return MAPPER.readValue(json, clazz);
        } catch (IOException e) {
            log.error("反序列化失败, json={}, clazz={}", json, clazz.getSimpleName(), e);
            throw new IllegalArgumentException("反序列化失败", e);
        }
    }

    public static <T> T formatJson(String json, TypeReference<T> typeRef) {
        try {
            log.debug("fromJson(TypeRef) <<< {}", json);
            return MAPPER.readValue(json, typeRef);
        } catch (IOException e) {
            log.error("反序列化失败, json={}, typeRef={}", json, typeRef, e);
            throw new IllegalArgumentException("反序列化失败", e);
        }
    }

    public static <T> T formatJson(InputStream in, Class<T> clazz) {
        try {
            log.debug("fromJson(InputStream) <<< {}", clazz.getSimpleName());
            return MAPPER.readValue(in, clazz);
        } catch (IOException e) {
            log.error("反序列化失败, clazz={}", clazz.getSimpleName(), e);
            throw new IllegalArgumentException("反序列化失败", e);
        }
    }

    public static <T> List<T> formatJsonList(String json, Class<T> clazz) {
        try {
            log.debug("fromJsonList <<< {}", json);
            return MAPPER.readValue(
                    json, MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
        } catch (IOException e) {
            log.error("反序列化为 List 失败, json={}, clazz={}", json, clazz.getSimpleName(), e);
            throw new IllegalArgumentException("反序列化为 List 失败", e);
        }
    }

    public static Map<String, Object> formatJsonMap(String json) {
        return formatJson(json, new TypeReference<Map<String, Object>>() {});
    }

    /* ---------- 转换 ---------- */
    public static <T> T convertValue(Object obj, Class<T> clazz) {
        return MAPPER.convertValue(obj, clazz);
    }

    public static <T> T convertValue(Object obj, TypeReference<T> typeReference) {
        return MAPPER.convertValue(obj, typeReference);
    }

    public static Map<String, Object> convertMap(Object obj) {
        return MAPPER.convertValue(obj, new TypeReference<Map<String, Object>>() {});
    }

    /* ---------- 树模型 ---------- */

    public static JsonNode readTree(String json) {
        try {
            log.debug("readTree <<< {}", json);
            return MAPPER.readTree(json);
        } catch (IOException e) {
            log.error("readTree 失败, json={}", json, e);
            throw new IllegalArgumentException("readTree 失败", e);
        }
    }

    public static ObjectNode createObjectNode() {
        return MAPPER.createObjectNode();
    }

    public static ArrayNode createArrayNode() {
        return MAPPER.createArrayNode();
    }

    /* ---------- 私有构造 ---------- */

    private JacksonUtil() {
        throw new AssertionError("No JacksonUtils instances for you!");
    }
}
